home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / rc-1.000 / rc-1 / rc-1.5-linux / b_expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-28  |  2.5 KB  |  107 lines

  1. /* expr has the grammar:   expr ::= expr operator expr | "(" expr ")" ;
  2.    with operator priority taken care of.  Resulting value goes to stdout.
  3.    Note that ":" operations are not implemented.   This is basically the
  4.    v7expr.c at uunet */
  5.  
  6. #define MAXPRIO    6
  7. #define OPERAND    20
  8. enum opnum {EOI,OR,AND,LT,LE,EQ,NE,GE,GT,ADD,SUB,MUL,DIV,MOD,LPAREN,RPAREN};
  9.  
  10. struct E_sop { char *text; enum opnum num; short prio;
  11. }E_ops[]={{"|",  OR,    6}, {"&",  AND,   5}, {"<",  LT,    4}, {"<=", LE,   4},
  12.           {"=",  EQ,    4}, {"!=", NE,    4}, {">=", GE,    4}, {">",  GT,   4},
  13.           {"+",  ADD,   3}, {"-",  SUB,   3}, {"*",  MUL,   2}, {"/",  DIV,  2},
  14.           {"%",  MOD,   2}, {"(",  LPAREN,0}, {")",  RPAREN,0}, {0,    0,   0}};
  15.  
  16. char **E_ip;
  17. struct E_sop *E_op;
  18. int E_error=0;
  19.  
  20. /* set global E_op to the op and return the opnum or the operand */
  21. E_lex(char* s) {
  22.     struct E_sop *op=E_ops;
  23.     if (s==0) {
  24.         E_op=0;
  25.         return EOI;
  26.     }
  27.     while (op->text) {
  28.         if (strcmp(s,op->text)==0) {
  29.             E_op=op;
  30.             return op->num;
  31.         }
  32.         op++;
  33.     }
  34.     E_op=0;
  35.     return OPERAND;
  36. }
  37.  
  38. int E_expr(int n, short prio) {
  39.     int res;
  40.     if (n==EOI) { E_error=1; return 1; }
  41.     if (n==LPAREN) {
  42.         res=E_expr(E_lex(*++E_ip), MAXPRIO);
  43.         if (E_lex(*++E_ip) != RPAREN) { E_error=1; return 1; }
  44.         return res;
  45.     }
  46.     if (n != OPERAND) { E_error=1; return 1; }
  47.     if (prio == 0) return atoi(*E_ip);
  48.     res = E_expr(n, prio - 1);
  49.     while ((n = E_lex(*++E_ip)) && E_op && E_op->prio == prio)
  50.         res = E_eval(res, n, E_expr(E_lex(*++E_ip), prio - 1));
  51.     E_ip--;
  52.     return res;
  53. }
  54.  
  55. int E_eval(int l1, int op, int l2) {
  56.     switch (op) {
  57.         case OR:  return l1 ? l1 : l2;
  58.         case AND: return (l1 && l2) ? l1 : 0;
  59.         case LT:  return l1 < l2;
  60.         case LE:  return l1 <= l2;
  61.         case EQ:  return l1 == l2;
  62.         case NE:  return l1 != l2;
  63.         case GE:  return l1 >= l2;
  64.         case GT:  return l1 > l2;
  65.         case ADD: return l1 + l2;
  66.         case SUB: return l1 - l2;
  67.         case MUL: return l1 * l2;
  68.         case DIV: return l1 / l2;
  69.         case MOD: return l1 % l2;
  70.     }
  71.     E_error=1;
  72.     return 1;
  73. }
  74.  
  75. #ifdef ADDON
  76.  
  77. #include "addon.h"
  78. typedef enum bool { FALSE, TRUE } bool;
  79. extern void set(bool);
  80. #define good_bye { set(TRUE); return; }
  81. #define bad_bye { set(FALSE); return; }
  82.  
  83. void b_expr(char** argv) {
  84.  
  85. #else
  86.  
  87. #define good_bye return 0;
  88. #define bad_bye return E_error;
  89.  
  90. int main(int argc, char** argv) {
  91.  
  92. #endif /* ADDON */
  93.  
  94.     int res;
  95.  
  96.     E_ip=&argv[1];
  97.     res=E_expr(E_lex(*E_ip), MAXPRIO);
  98.  
  99.     if (*++E_ip != 0)
  100.         bad_bye
  101.     printf("%ld\n", res);
  102.     if (E_error==1)
  103.         bad_bye
  104.     else
  105.         good_bye
  106. }
  107.